﻿# 需要的依赖
# pip install pyautogui -i https://pypi.tuna.tsinghua.edu.cn/simple/
# pip install pillow
# pip install PyQt5
from PyQt5.QtWidgets import QSystemTrayIcon, QMainWindow, QApplication, QMenu, QAction, QMessageBox
from PyQt5.QtGui import QIcon, QPixmap
import pyautogui
import sys
import os
import socketserver
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib
import json
from threading import Thread
import socket
import time
import tkinter.messagebox
import ctypes


class TrayModel(QSystemTrayIcon):
    def __init__(self, Window):
        super(TrayModel, self).__init__()
        self.window = Window
        self.init_ui()

    def init_ui(self):
        # 初始化菜单
        self.menu = QMenu()
        self.quit_action = QAction('退出', self, triggered=self.quit_clock)
        self.menu.addAction(self.quit_action)
        self.setContextMenu(self.menu)
        self.setIcon(QIcon(os.path.dirname(__file__) + '/Pwaerm.ico'))
        self.icon = self.MessageIcon()

    def quit_clock(self):
        stop_thread(webThread)
        app.quit()


class HttpHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.deParams(self.path)

    def do_POST(self):
        params = self.rfile.read(int(
            self.headers['content-length'])).decode("utf-8")
        self.deParams(params)

    def deParams(self, _params):
        params = _params.split('&')
        try:
            args = []
            for _key in params:
                _v = _key.split("=")
                if (len(_v) == 2):
                    args.append(_v[1])
        except:
            args = []
        self._response(self.path, args)

    def _response(self, path, args):
        Thread(target=mouseHandler, args=(args,)).start()
        result = {"status": 1, "msg": "执行成功"}
        # result = mouseHandler(args)
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(result).encode())


def openServer(_port):
    httpd = HTTPServer(('', _port), HttpHandler)
    httpd.serve_forever()


def mouseHandler(args: list):
    print("参数为:", args)
    if len(args) > 0:
        if args[0] == "click":
            # 参数为 click 原地点击
            p = pyautogui.position()
            pyautogui.click(p.x, p.y)
        if args[0] == "clickPoint":
            # 参数为 clickPoint x y 点击指定坐标
            pyautogui.click(int(args[1]), int(args[2]))
        elif args[0] == 'move':
            # 参数为 move xd yd 鼠标从当前位置移动
            pyautogui.move(int(args[1]), int(args[2]), 0.2)
        elif args[0] == 'moveTo':
            # 参数为 moveTo x y 鼠标移动到目标位置
            pyautogui.moveTo(int(args[1]), int(args[2]), 0.2)
        # elif args[0] == 'moveAndClick':
        #     # 参数为 moveAndClick x y 鼠标移动到目标位置,然后点击
        #     pyautogui.moveTo(int(args[1]), int(args[2]), 0.5)
        #     pyautogui.click(int(args[1]), int(args[2]))
        elif args[0] == 'scroll':
            # 参数为 scroll 鼠标滚轮滚动
            pyautogui.scroll(int(args[1]))
        elif args[0] == 'write':
            # 参数为write时为模拟键盘输入
            pyautogui.typewrite(args[1], 0.2)
        result = {
            "status": 1,
            "msg": "success"
        }
    else:
        result = {
            "status": 0,
            "msg": "缺少参数"
        }
    return result


def net_is_used(port, ip='127.0.0.1'):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s.connect((ip, port))
        s.shutdown(2)
        print('%s:%d is used' % (ip, port))
        return True
    except:
        print('%s:%d is unused' % (ip, port))
        return False


class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setFixedSize(300, 200)
        self.tray = TrayModel(self)
        self.tray.show()


def openServer(_port):
    print(_port)
    httpd = HTTPServer(('', _port), HttpHandler)
    httpd.serve_forever()


def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.setWindowTitle("P娃儿猫助手v1.0")
    window.setFixedSize(200, 160)
    # Thread(target=openServer, args=(2000, )).start()
    if len(sys.argv[1:]):
        mouseHandler(sys.argv[1:])
    else:
        if not net_is_used(2000):
            webThread = Thread(target=openServer, args=(2000, )).start()
            window.setWindowIcon(
                QIcon(os.path.dirname(__file__) + '/Pwaerm.ico'))
            # window.show()
            sys.exit(app.exec_())
        else:
            print("端口已经被占用")
            icon = QIcon()
            icon.addPixmap(QPixmap(os.path.dirname(__file__) + '/Pwaerm.ico'))
            box = QMessageBox()
            box.setWindowIcon(icon)
            box.setWindowTitle("P娃儿猫提示：")
            box.setStandardButtons(QMessageBox.Ok)
            box.button(QMessageBox.Ok).setText("确定")
            box.setStyleSheet("QLabel{min-width: 260px;min-height:50}")
            box.setText("端口已经被占用，程序可能已经启动")
            box.exec_()
            # tkinter.messagebox.showinfo(title = 'P娃儿猫提示：', message = '端口已经被占用，程序可能已经启动。')
